﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DynamicExpresso;
using Newtonsoft.Json.Linq;
using ST.Core;



namespace ST.Core.Util
{
    public class Calc
    {
        byte[] data;
        public void SetData(byte[] odata, bool IsBit)
        {
            if (IsBit)
            {
                data = ByteUtil.ConvertModbusBitsToBytes(odata);
            }
            else
            {
                data = ByteUtil.PrependZero(odata);
            }
        }

        /// <summary>
        /// 获取指定索引的字节
        /// </summary>
        /// <param name="data">字节数组</param>
        /// <param name="index">索引位置</param>
        /// <returns>指定索引的字节</returns>
        public byte Value(int index)
        {
            if (data == null)
                throw new ArgumentNullException(nameof(data));
            if (index < 0 || index >= data.Length)
                throw new ArgumentOutOfRangeException(nameof(index));

            return data[index];
        }
        public byte BValue(int index)
        {
            return Value(index);
        }
        /// <summary>
        /// 从原数组第二位开始获取UInt16值
        /// </summary>
        /// <param name="data">字节数组</param>
        /// <param name="index">开始位置（从1开始，实际从第二位开始）</param>
        /// <returns>UInt16值</returns>
        public ushort WValue(int index)
        {
            if (data == null)
                throw new ArgumentNullException(nameof(data));
            if (index < 1 || index + 1 >= data.Length)
                throw new ArgumentOutOfRangeException(nameof(index));

            // 从第二位开始计算，index=1对应数组的第二个元素
            int startIndex = index;
            return (ushort)((data[startIndex] << 8) | data[startIndex + 1]);
        }
        /// <summary>
        /// 从原数组第二位开始获取UInt16值
        /// </summary>
        /// <param name="data">字节数组</param>
        /// <param name="index">开始位置（从1开始，实际从第二位开始）</param>
        /// <returns>UInt16值</returns>
        
        public ushort JCQValue(int index)
        {
            index = (index - 1) * 2+1;
            if (data == null)
                throw new ArgumentNullException(nameof(data));
            if (index < 1 || index + 1 >= data.Length)
                throw new ArgumentOutOfRangeException(nameof(index));

            // 从第二位开始计算，index=1对应数组的第二个元素
            int startIndex = index;
            return (ushort)((data[startIndex] << 8) | data[startIndex + 1]);
        }
        /// <summary>
        /// 从原数组第二位开始获取整数
        /// </summary>
        /// <param name="data">字节数组</param>
        /// <param name="index">开始位置（从1开始，实际从第二位开始）</param>
        /// <returns>整数</returns>
        public int IValue(int index)
        {
            if (data == null)
                throw new ArgumentNullException(nameof(data));
            if (index < 1 || index + 3 >= data.Length)
                throw new ArgumentOutOfRangeException(nameof(index));

            // 从第二位开始计算，index=1对应数组的第二个元素
            int startIndex = index;
            return (data[startIndex] << 24) |
                   (data[startIndex + 1] << 16) |
                   (data[startIndex + 2] << 8) |
                   data[startIndex + 3];
        }
        /// <summary>
        /// 从原数组第二位开始获取float值，遵循Modbus字节顺序
        /// </summary>
        /// <param name="data">字节数组</param>
        /// <param name="index">开始位置（从1开始，实际从第二位开始）</param>
        /// <returns>float值</returns>
        public float FValue(int index)
        {
            if (data == null)
                throw new ArgumentNullException(nameof(data));
            if (index < 1 || index + 3 >= data.Length)
                throw new ArgumentOutOfRangeException(nameof(index));

            // 从第二位开始计算，index=1对应数组的第二个元素
            int startIndex = index;
            byte[] floatBytes = new byte[4];
            floatBytes[0] = data[startIndex + 1];  // 高字节
            floatBytes[1] = data[startIndex];      // 低字节
            floatBytes[2] = data[startIndex + 3];  // 高字节
            floatBytes[3] = data[startIndex + 2];  // 低字节

            return BitConverter.ToSingle(floatBytes, 0);
        }


       
        public UInt16 CalcUInt16(string fml ,List<UInt16Value> l)
        {
            var interpreter=new Interpreter();  
            foreach (var m in l)
            {
                interpreter.SetVariable(m.Name,m.Id);
            }
            var d = interpreter.Eval<UInt16>(fml);
            return d;
        }

        public float CalcFloat(string fml, List<UInt16Value> l)
        {
            var interpreter = new Interpreter();
            foreach (var m in l)
            {
                interpreter.SetVariable(m.Name, m.Id);
            }
            var d = interpreter.Eval<float>(fml);
            return d;
        }
        public decimal CalcDecimal(string fml, List<UInt16Value> l)
        {
            var  v=CalcFloat(fml, l);
            return Convert.ToDecimal(v);
        }

        /// <summary>
        /// 获取byte的指定bit位的值
        /// </summary>
        /// <param name="b">字节</param>
        /// <param name="index">bit位索引（从1开始）</param>
        /// <returns>bit位的值（0或1）</returns>
        public int BitValue(byte b, int index)
        {
            if (index < 1 || index > 8)
                throw new ArgumentOutOfRangeException(nameof(index));

            return (b >> (index - 1)) & 0x01;
        }


        void PrepareFunc(Interpreter interpreter)
        {
             
            interpreter.SetFunction("Value", Value);
            interpreter.SetFunction("BitValue", BitValue);
            interpreter.SetFunction("BValue", BValue);
            interpreter.SetFunction("WValue", WValue);
            interpreter.SetFunction("IValue", IValue);
            interpreter.SetFunction("FValue", FValue);
            

            interpreter.SetFunction("返回数据", Value);
            interpreter.SetFunction("比特值", BitValue);
            interpreter.SetFunction("字节值", BValue);
            interpreter.SetFunction("位值", BValue);
            interpreter.SetFunction("寄存器值", JCQValue);
            interpreter.SetFunction("整数值", IValue);
            interpreter.SetFunction("浮点数值", FValue);

             
        }
        public decimal CalcAll(string fml, List<UInt16Value> l)
        {
            var interpreter = new Interpreter();
            var mjd = l.Where(a => a.Name == "监测精度").FirstOrDefault();
            if (mjd == null)
            {
                mjd = new UInt16Value { Id = 1, Name = "监测精度" };
                l.Add(mjd); 
            }
            foreach (var m in l)
            {
                if(m.Name== "监测精度")
                {
                    interpreter.SetVariable(m.Name, Math.Pow(10,m.Id)  );
                }
                else
                {
                    interpreter.SetVariable(m.Name, m.Id);
                }
                
            }
            PrepareFunc(interpreter);
            var v = interpreter.Eval<float>(fml);
          
            return Convert.ToDecimal(v);
        }


    }
}
